﻿// Filename:  Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;


namespace HotelResSystem2
{
    public partial class Form1 : Form 
    {
        private static Form1 Form1Instance;
        static readonly object padlock = new object();

        private Form1()
        {
            InitializeComponent();

            // Disable the event handlers, initialize the values, and reenable the event handlers
            RateDiscComboBox.SelectedIndexChanged -= RateDiscComboBox_SelectedIndexChanged;
            RateTypComboBox.SelectedIndexChanged -= RateTypComboBox_SelectedIndexChanged;
            populateDiscountCombos();
            RateTypComboBox.SelectedIndex = 0;
            RateDiscComboBox.SelectedIndex = 0;
            RateDiscComboBox.SelectedIndexChanged += RateDiscComboBox_SelectedIndexChanged;
            RateTypComboBox.SelectedIndexChanged += RateTypComboBox_SelectedIndexChanged;
            setNightlyRate();
        }

        public static Form1 GetInstance()
        {
            lock (padlock)
            {
                if (Form1Instance == null)
                {
                    Form1Instance = new Form1();
                }
                return Form1Instance;
            }
        }

        private void populateDiscountCombos()
        { 
            foreach (Discount disc in DiscountFactory.getDiscountList())
            {
                RateDiscComboBox.Items.Add(disc);
            }
            foreach (RoomRate rr in RoomRateFactory.GetRoomRateList())
            {
                RateTypComboBox.Items.Add(rr);
            }
        }

        public string GenerateRandomCode(int length)
        {
            string charPool = "ABCDEFGOPQRSTUVWXY1234567890ZHIJKLMN";
            StringBuilder rs = new StringBuilder();
            Random random = new Random();
            for (int i = 0; i < length; i++)
            {
                rs.Append(charPool[(int)(random.NextDouble() * charPool.Length)]);
            }
            return rs.ToString();
        }

        private void CreateButton_Click(object sender, EventArgs e)
        {
            // Create a new reservation ID and set it in the form before generating the reservation
            string resID = GenerateRandomCode(8);

            // Record the reservation ID into the text box
            ResIDTxtBox.Text = resID;

            Reservation reservation = CreateReservationFromForm();
            if (reservation != null)
            {
                // Save the reservation in the hotel system
                ReservationSystem.GetInstance().createNewReservation(reservation);

                // Indicate that the reservation has been created
                MessageBox.Show("Reservation has been successfully created.", "Reservation Created", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            ClearForm();
        }

        private void RmStatButton_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(RmNumTxtBox.Text))
            {
                DateTime time1 = InDateTimePicker.Value;
                DateTime time2 = OutDateTimePicker.Value;
                int roomNum = Convert.ToInt32(RmNumTxtBox.Text);

                RoomInventory rooms = new RoomInventory();
                PropertyListener prop = new RoomInfoFrame();
                prop.initialize(rooms);
                rooms.checkRoomStatus(roomNum, time1, time2); 
            }
        }

        private void RmAvailButton_Click(object sender, EventArgs e)
        {
            //Use dates entered to text boxes to use check status foreach room
            //make list of all available rooms
            DateTime time1 = InDateTimePicker.Value;
            DateTime time2 = OutDateTimePicker.Value;

            RoomInventory rooms = new RoomInventory();
            PropertyListener prop = new AvailRoomsProps();
            prop.initialize(rooms);

            rooms.findAvailableRooms(time1, time2);
        }

        public void setRoomAvailTxt(bool value) 
        {
            if (value)
            {
                RoomAvailTxtBx.ForeColor = Color.Green;
                RoomAvailTxtBx.Text = "Available!";
            }
            else
            {
                RoomAvailTxtBx.ForeColor = Color.Red;
                RoomAvailTxtBx.Text = "Unavailable!";
            }
        }

        public void setRoomNumber(string roomNum)
        {
            RmNumTxtBox.Text = roomNum;
        }


        private void SearchButton_Click(object sender, EventArgs e)
        {
            string lastName = LastNameTxtBox.Text;
            string resNum = ResIDTxtBox.Text;
            Reservation res = null;

            // neither search term entered on GUI.
            if ((resNum == "") && (lastName == ""))
            {
                // display error msg
                MessageBox.Show("Please enter Reservation Number or Lastname");
            }

            if ((resNum == "") && (lastName != ""))
            {
                // no Reservation Number entered on GUI.  Use lastName
                res = ReservationSystem.GetInstance().lookUpResByLastName(lastName);
            }
            else if ((resNum != "") && (lastName == ""))
            {
                // no lastName entered on GUI.  Use Reservation Number
                res = ReservationSystem.GetInstance().lookUpResByID(resNum);
            }
            if (res != null && !string.IsNullOrEmpty(res.ResID))
            {
                // Reservation found--populate GUI
                MessageBox.Show("Found Reservation");
                ResIDTxtBox.Text = res.ResID;
                FirstNameTxtBox.Text = res.PrimaryGuest.ContactInfo.FirstName;
                AddressTxtBox.Text = res.PrimaryGuest.ContactInfo.Address;
                CityTxtBox.Text = res.PrimaryGuest.ContactInfo.City;
                StateComboBox.Text = res.PrimaryGuest.ContactInfo.State;
                ZipTxtBox.Text = res.PrimaryGuest.ContactInfo.ZIP.ToString();
            }
        }

        private void RateDiscComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            calculateTotals();
        }

        private void calculateTotals()
        {
            Discount curDisc = (Discount)RateDiscComboBox.SelectedItem;
            string numDiscDays = NumDaysNumUpDown.Value.ToString();
            int curDaysRes = DaysStayComboBox.FindString(numDiscDays);

            string curRmTyp = RateTypComboBox.SelectedItem.ToString();
            float baseRate = Convert.ToSingle(NightlyRate.Text);
            float rate = curDaysRes * baseRate;

            double disctedRate = rate - rate * curDisc.Percentage;
            SubTotTxtBox.Text = Convert.ToString(disctedRate);
            float othercharges; 
            float.TryParse(OthChrgTxtBox.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out othercharges);
            TotalDueTextBox.Text = (disctedRate - othercharges).ToString();

        }

        private void RateTypComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            //  Add code to get the type selected
            //  Add case statement to assign nightly rate based on type of room chosen
            //  Return Nightly Rate?

            setNightlyRate();
            TotalDueTextBox.Text = Convert.ToString(0.0);
            calculateTotals();                                
           
        }

        private void setNightlyRate()
        {
            NightlyRate.Text = ((RoomRate)RateTypComboBox.SelectedItem).Amount.ToString();
        }

        
        private void OnLeaveField(object sender, EventArgs e)
        {   
            string numDays = NumDaysNumUpDown.Value.ToString();
            int curDaysRes = DaysStayComboBox.FindString(numDays);

            float baseRate = 0.0f;
            if (float.TryParse(NightlyRate.Text, out baseRate))
            {
                float rate = curDaysRes * baseRate;
                TotalDueTextBox.Text = Convert.ToString(rate);
            }
        }

        private void DaysStayComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {            
           int days = Convert.ToInt32(DaysStayComboBox.Text);
           calculateTotals();
        }
      
   ///////////////////////
          
        
        
        private void LeaveComboBox(object sender, EventArgs e)
        {
            {
                //  Add code to get number of days stay

                // Get the currently selected item in the ListBox. 
                string curNumDays = DaysStayComboBox.SelectedItem.ToString();

                // Find the string in ListBox2. 
                int curDaysRes = DaysStayComboBox.FindString(curNumDays);

                
                float baseRate = Convert.ToSingle(NightlyRate.Text);

                float rate = curDaysRes * baseRate;
                TotalDueTextBox.Text = Convert.ToString(rate);  
                
              }
            
        }

        private void NumDaysNumUpDown_ValueChanged(object sender, EventArgs e)
        {
            calculateTotals();
        }

        private void ChkInButton_Click(object sender, EventArgs e)
        {
            // Check in guest if reservation info is populated
            Reservation reservation = CreateReservationFromForm();

            if (reservation != null)
            {
                ReservationSystem.GetInstance().CheckIn(reservation);
                MessageBox.Show("Guest has been checked in.", "Checked In", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void ChkOutButton_Click(object sender, EventArgs e)
        {
            // Check out guest if reservation info is populated
            Reservation reservation = CreateReservationFromForm();
            double additionalCharges = 0.0;
            double.TryParse(OthChrgTxtBox.Text, out additionalCharges);

            if (reservation != null)
            {
                Bill bill = PaymentSystem.GetInstance().PrepareBill(reservation, additionalCharges);
                FormBill formBill = new FormBill(bill);
                DialogResult result = formBill.ShowDialog();
                if (result == DialogResult.OK)
                {
                    ReservationSystem.GetInstance().CheckOut(reservation);
                    MessageBox.Show("Guest has been checked out.", "Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    ClearForm();
                }
            }
        }

        private Reservation CreateReservationFromForm()
        {
            Reservation reservation = new Reservation();
            string resID = ResIDTxtBox.Text;
            string lastName = LastNameTxtBox.Text;
            string firstName = FirstNameTxtBox.Text;
            string address = AddressTxtBox.Text;
            string city = CityTxtBox.Text;
            string state = StateComboBox.Text;
            string zip = ZipTxtBox.Text;
            int zipCode = 0;

            DateTime checkinDate = InDateTimePicker.Value;
            DateTime checkoutDate = OutDateTimePicker.Value;

            if (string.IsNullOrEmpty(lastName))
            {
                // Invalid last name
                MessageBox.Show("Invalid last name.", "Invalid Last Name", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

            if (checkoutDate < checkinDate)
            {
                // Invalid checkin/checkout dates
                MessageBox.Show("The check out date cannot be before the check in date.", "Invalid Dates", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }
            
            //if (double.TryParse(Addition

            reservation.PrimaryGuest.ContactInfo.LastName = lastName;
            reservation.PrimaryGuest.ContactInfo.FirstName = firstName;
            reservation.PrimaryGuest.ContactInfo.Address = address;
            reservation.PrimaryGuest.ContactInfo.City = city;
            reservation.PrimaryGuest.ContactInfo.State = state;
            // If the parse is successful, store the zip code
            if (int.TryParse(zip, out zipCode))
            {
                reservation.PrimaryGuest.ContactInfo.ZIP = zipCode;
            }
            reservation.ResID = resID;
            reservation.CheckInDate = checkinDate;
            reservation.CheckOutDate = checkoutDate;
            reservation.NumberOfDays = (int)NumDaysNumUpDown.Value;
            reservation.NumberOfAdults = (int)NumAdultNumUpDown.Value;
            reservation.NumberOfChildren = (int)NumChildNumUpDown.Value;
            double nightlyRate = 0.0;
            double.TryParse(NightlyRate.Text, out nightlyRate);
            reservation.NightlyRate = nightlyRate;
            string rateType = RateTypComboBox.SelectedItem.ToString();
            reservation.RateType = RoomRateFactory.GetRoomRate(rateType);
            string discount = RateDiscComboBox.SelectedItem.ToString();
            reservation.Discount = DiscountFactory.GetDiscount(discount);
            return reservation;
        }

        private void ClearForm()
        {
          ResIDTxtBox.Text = "";
          LastNameTxtBox.Text = "";
          FirstNameTxtBox.Text = "";
          AddressTxtBox.Text = "";
          CityTxtBox.Text = "";
          StateComboBox.Text = "";
          ZipTxtBox.Text = "";
        }
    }
}
